import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;

import controlP5.Bang;
import controlP5.Button;
import controlP5.ControlCanvas;
import controlP5.ControlEvent;
import controlP5.ControlGroup;
import controlP5.ControlP5;
import controlP5.ListBox;
import controlP5.RadioButton;
import controlP5.ScrollList;
import controlP5.Toggle;
import processing.core.PApplet;
import processing.core.PFont;
import java.sql.ResultSetMetaData;

public class Main extends PApplet {
	//static parameters
	public final static int WIDTH = 800;
	public final static int HEIGHT = 800;	
	public final static int FRAME_RATE = 30;
	
	//public variables to access Processing and ControlP5 libraries
	public ControlP5 controlP5;
	public PApplet theApplet = this;
	public CSVConn myconn;
	
	//static variables 
	public static ArrayList<MainGroup> groupList;  //holds all created groups
	public static MainGroup main;				   //group "main" to hold all objects that do not fall in another group
	public static DrawObject activeObject;		   //object selected by user, when mouse button is not down it takes null value
	public static HashMap<String, Integer> nameToId;				   //hashmap converting group names to ids
	public static HashMap<Integer, String> idToName;				   //hashmap converting group ids to names
	public static int nextId;
	
	
	int testCanvas_xPos = 100;
	int testCanvas_yPos = 200;
	int testCanvas_width = 300;
	int testCanvas_height = 400;
	
	
	//sets up window and p5 start parameters
	public void setup() {
		size(WIDTH,HEIGHT);
		smooth();
		frameRate(FRAME_RATE);
		
		controlP5 = new ControlP5(this);
		nameToId = new HashMap<String, Integer>();
		idToName = new HashMap<Integer, String>();
		nextId = 0;
		
		initializeGroups();
		initializeData();
		
		
	}
	
	//draws objects at each iteration of the buffer
	//should not need to use at this level
	public void draw() {
		 background(0);	
		 //drawStuff();
	}
	void drawStuff() {
		rect(0,0,50,50);
	}
	
	//handles mouse press event
	//checks all open groups to see if mouse click is in their range
	//goes in order specified by groupList, then checks "main" group
	public void mousePressed() {
		for(MainGroup g: groupList) {
			if(g.handlePress(mouseX, mouseY)) {
				return;
			}
			main.handlePress(mouseX, mouseY);
		}
	}
	
	//handles mouse release event
	//calls handleRelease function in DrawObject class
	public void mouseReleased() {
		if(activeObject != null) {
			activeObject.handleRelease(mouseX, mouseY);
		}
	}
	
	
	//Initialize a couple groups for testing purposes
	void initializeGroups() {
		groupList = new ArrayList<MainGroup>();
		main = new MainGroup( "MainGroup", this, controlP5,0, 0, width, height);
		main.theGroup.setBackgroundColor(color(0,0,0,255));
				
		for(int i = 0; i< 1; i++) {
			MainGroup g = new MainGroup( "Group: "+i, this, controlP5,testCanvas_xPos + 420*(i), testCanvas_yPos+ 50*i, testCanvas_width, testCanvas_height);
			groupList.add(g);
			DrawObject c = new DrawObject(this, g.theCanvas, g.theGroup, 100, 100);
			g.theCanvas.drawQueue.add(c);
			g.theCanvas.parent.theGroup.addCanvas(c);
		}		
	}
	
	//Initialize data
	void initializeData() {
		
		MainGroup g = new MainGroup( "Data", this, controlP5,testCanvas_xPos + 300, testCanvas_yPos+ 50, 200, 50);
		groupList.add(g);
		g.theGroup.setLabel("Data Control Group");
		
		RadioButton r;
		  r = controlP5.addRadioButton("dataType",20,10);
		  r.setColorForeground(color(120,50,0));
		  r.setColorActive(color(255));
		  r.setColorLabel(color(0,0,100));
		  r.setItemsPerRow(1);
		  r.setId(nextId++);
		  nameToId.put("dataTypeRadio", r.id());

		  addToRadioButton(r,"Genes",1);
		  addToRadioButton(r,"Annotations",2);
		  addToRadioButton(r,"Expression",3);
		r.setGroup("Data");
		
	}
	
	void addToRadioButton(RadioButton theRadioButton, String theName, int theValue ) {
		Toggle t = theRadioButton.addItem(theName,theValue);
	  	t.captionLabel().setColorBackground(color(80));
	  	t.captionLabel().style().movePadding(2,0,-1,2);
	  	t.captionLabel().style().moveMargin(-2,0,0,-3);
	  	t.captionLabel().style().backgroundWidth = 70;
	}
	
	void controlEvent(ControlEvent theEvent) {
		if (theEvent.isGroup()) {
		    // an event from a group e.g. scrollList
			if(theEvent.group().id() == nameToId.get("dataTypeRadio")) {
				setDataOptions((int)theEvent.group().value());
				return;
			}
			//println(theEvent.group().id());
			else if(theEvent.group().id() == nameToId.get("annotationSelectorList")) {
				ListBox l = (ListBox) controlP5.getGroup("annotationSelectorList");
				String annotationName = idToName.get((int)theEvent.group().value());
				l.removeItem(annotationName);
				ListBox l2 = (ListBox) controlP5.getGroup("selectedAnnotations");
				l2.addItem(annotationName, nextId);
				idToName.put(nextId, annotationName);
				nameToId.put(annotationName, nextId++);
				
				showSelectAnnotationsGroup(annotationName);
				return;
			}
			else if(theEvent.group().id() == nameToId.get("geneSelectorList")) {
				ListBox l = (ListBox) controlP5.getGroup("geneSelectorList");
				String geneName = idToName.get((int)theEvent.group().value());
				l.removeItem(geneName);
				ListBox l2 = (ListBox) controlP5.getGroup("selectedGenes");
				l2.addItem(geneName, nextId);
				idToName.put(nextId, geneName);
				nameToId.put(geneName, nextId++);
				//println(geneName);
				return;
			}
		    println(theEvent.group().value()+" from "+theEvent.group());
		    println(theEvent.group().id()+" from "+idToName.get(theEvent.group().value()));
		 }
		
	}
	
	void showSelectAnnotationsGroup(String annotation) {
		RadioButton r;
		  r = controlP5.addRadioButton("annotationList",200,10);
		  r.setColorForeground(color(120,50,0));
		  r.setColorActive(color(255));
		  r.setColorLabel(color(0,0,100));
		  r.setLabel("Genes to Show for " + annotation + " annotation");
		  r.setItemsPerRow(1);
		  r.setId(nextId++);
		  nameToId.put("annotationRadio", r.id());
		  
		myconn = new CSVConn("../data");
		if(myconn.query("SELECT DISTINCT " + annotation  + " FROM partial_annotations4329") == 1) {
			ResultSet results = myconn.getResults();
			try
			{
				while (results.next())
				{
					addToRadioButton(r, results.getString(annotation) ,nextId);
					idToName.put(nextId, results.getString(annotation));
					nameToId.put(results.getString(annotation), nextId++);
					
				}
			}
			catch(Exception e)
			{
				System.out.println("Error in Main-> " + e);
			}
		}
		r.setGroup("Data");
	}
	
	void setDataOptions(int dataTypeRadioValue) {
		switch(dataTypeRadioValue) {
		case(1): 
			groupList.get(1).theGroup.setBackgroundHeight(400);
		
			if(controlP5.group("geneSelectorList") == null) {
				ListBox slist = controlP5.addListBox("geneSelectorList",10,75,80,180);
				slist.setLabel("Gene List");
				slist.setGroup("Data");
				slist.setId(nextId);
				idToName.put(nextId, "geneSelectorList");
				nameToId.put("geneSelectorList", nextId++);
				
				ListBox selectedGenes = controlP5.addListBox("selectedGenes",105,75,80,180);
				selectedGenes.setLabel("Selected");
				selectedGenes.setGroup("Data");
				selectedGenes.setId(nextId);
				idToName.put(nextId, "selectedGenes");
				nameToId.put("selectedGenes", nextId++);
				
				myconn = new CSVConn("../data");		
				if(myconn.query("SELECT * FROM partial_genes4329") == 1) {
					ResultSet results = myconn.getResults();	
					try
					{
						// dump out the results
						while (results.next())
						{
							slist.addItem(results.getString("Gene"), nextId);
							idToName.put(nextId, results.getString("Gene"));
							nameToId.put(results.getString("Gene"), nextId++);
							
						}
					}
					catch(Exception e)
					{
						System.out.println("Error in Main-> " + e);
					}
				}
			}
			else if( controlP5.group("geneSelectorList").isVisible() == false) {
				controlP5.group("geneSelectorList").setVisible(true);
				controlP5.group("selectedGenes").setVisible(true);
			}
		break;
		case(2):
			groupList.get(1).theGroup.setBackgroundHeight(400);
			
			if(controlP5.group("geneSelectorList") != null)
				controlP5.group("geneSelectorList").setVisible(false);
			
			if(controlP5.group("selectedGenes") != null)
				controlP5.group("selectedGenes").setVisible(false);
			
			 ListBox slist = controlP5.addListBox("annotationSelectorList",10,75,160,60);
			 slist.setLabel("Annotation List");
			 slist.setGroup("Data");
			 slist.setId(nextId);
			 idToName.put(nextId, "annotationSelectorList");
			 nameToId.put("annotationSelectorList", nextId++);
			
			 ListBox selectedAnnotations = controlP5.addListBox("selectedAnnotations",10,170,160,60);
			 selectedAnnotations.setLabel("Selected");
			 selectedAnnotations.setGroup("Data");
			 selectedAnnotations.setId(nextId);
			 idToName.put(nextId, "selectedAnnotations");
			 nameToId.put("selectedAnnotations", nextId++);
			 
			 
			myconn = new CSVConn("../Data");		
			if(myconn.query("SELECT * FROM partial_annotations4329") == 1) {
				ResultSet results = myconn.getResults();
				try
				{
					// dump out the results
					ResultSetMetaData rsMetaData = results.getMetaData();
					int numberOfColumns = rsMetaData.getColumnCount();
					String[] annotationNames = new String[numberOfColumns];
					 for (int i = 1; i <= numberOfColumns; i++) {
						 if(!rsMetaData.getColumnLabel(i).equals("")) {
							 annotationNames[i-1] = rsMetaData.getColumnLabel(i);
							 slist.addItem(annotationNames[i-1], nextId);
							 idToName.put(nextId, annotationNames[i-1]);
							 nameToId.put(annotationNames[i-1], nextId++);
						     System.out.println(rsMetaData.getColumnLabel(i));
						 }
					 }
				}
				catch(Exception e)
				{
					System.out.println("Error in Main-> " + e);
				}
			}
			
		break;
		case(3):
			groupList.get(1).theGroup.setBackgroundHeight(400);
		
			if(controlP5.group("geneSelectorList") != null)
				controlP5.group("geneSelectorList").setVisible(false);
			
			if(controlP5.group("selectedGenes") != null)
				controlP5.group("selectedGenes").setVisible(false);
			
		break;
		default:
			groupList.get(1).theGroup.setBackgroundHeight(50);
		
			if(controlP5.group("geneSelectorList") != null)
				controlP5.group("geneSelectorList").setVisible(false);
			
			if(controlP5.group("selectedGenes") != null)
				controlP5.group("selectedGenes").setVisible(false);
		}
		
	}

}
